﻿using Dapper;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using YaAppoint.DappperConnection;

namespace YaAppoint.DapperRepositories
{
    /// <summary>
    /// 检查申请项目仓储
    /// </summary>
    public class DapperExamApplyItemRepository(IConnectionProvider connectionProvider,
                                               IConfiguration configuration,
                                               IRepository<ApplyDepartment, Guid> applyDepRepository) : IDapperExamApplyItemRepository, ITransientDependency
    {
        private readonly IConnectionProvider _connectionProvider = connectionProvider;
        private readonly IConfiguration _configuration = configuration;
        private readonly IRepository<ApplyDepartment, Guid> _applyDepRepository = applyDepRepository;

        /// <summary>
        /// 获取his检查申请项目
        /// </summary>
        /// <param name="number"></param>
        /// <param name="userData"></param>
        /// <param name="deviceTypes"></param>
        /// <param name="funcSearchNumber">返回string的委托，设置number匹配哪些字段</param>
        /// <param name="actionAddConditions">额外条件</param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public async Task<List<HisExamApplyItemDto>> GetExamApplyItemsAsync(string? number, Dictionary<string, object> userData, List<string>? deviceTypeCodes, Func<string>? funcSearchNumber, Func<Dictionary<string, object>, string,string>? actionAddConditions)
        {
            var databaseType = _connectionProvider.GetDatabaseType();
            var connectionStr = _configuration["ConnectionStrings:HisDb"];
            if (string.IsNullOrEmpty(connectionStr))
            {
                throw new BusinessException(CustomErrorCodes.NoHisConnectionNotFund);
            }
            string parmSign = databaseType.GetParameterSign();
            using var conn = _connectionProvider.GetDbConnection(connectionStr, databaseType);
            conn.Open();
            string condition = $"where 1=1";
            Dictionary<string,object> parameters = new Dictionary<string,object>();


            #region 过滤字段
            
            for (int i = 0; i < userData.Count; i++)
            {
                var item = userData.ElementAt(i);

                // 就诊卡号
                if (item.Key.Equals("medicalCardNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("medicalCardNumber", value);
                        condition += $" and MedicalCardNumber={parmSign}{item.Key} ";
                    }
                }

                // 姓名
                if (item.Key.Equals("name"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("name", value);
                        condition += $" and Name= {parmSign}{item.Key} ";
                    }
                }


                // 门诊号
                if (item.Key.Equals("outPatientNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("outPatientNumber", value);
                        condition += $" and OutPatientNumber = {parmSign}{item.Key} ";
                    }
                }

                // 住院号
                if (item.Key.Equals("inPatientNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("inPatientNumber", value);
                        condition += $" and InPatientNumber = {parmSign}{item.Key} ";
                    }
                }

                // 体检号
                if (item.Key.Equals("physicalExamNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("physicalExamNumber", value);
                        condition += $" and PhysicalExamNumber = {parmSign}{item.Key} ";
                    }
                }

                // 联系方式
                if (item.Key.Equals("phoneNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrEmpty(value))
                    {
                        parameters.Add("phoneNumber", value);
                        condition += $" and PhoneNumber = {parmSign}{item.Key}";
                    }
                }

                // 日期范围
                if (item.Key.Equals("range"))
                {
                    var range = JsonConvert.DeserializeObject<List<DateTime>>(userData["range"].ToString())  ;
                    var startTime = range[0];
                    var endTime = range[1];
                    parameters.Add("startTime", startTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    parameters.Add("endTime", endTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    condition += $" and (ApplyTime >= {parmSign}startTime and ApplyTime < {parmSign}endTime)";
                }

                // 证件号码
                if (item.Key.Equals("idCardNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        parameters.Add("idCardNumber", value);
                        condition += $" and IdCardNumber={parmSign}{item.Key}";
                    }
                }

                // 申请科室
                if (item.Key.Equals("applyDepartments"))
                {
                    var value =JsonConvert.DeserializeObject<List<string>>(item.Value.ToString());
                    if (value != null && value.Count > 0)
                    {
                        var applyDepartmentIds = value.Select(Guid.Parse);
                        var applyDepartments = await _applyDepRepository.GetListAsync(e => applyDepartmentIds.Contains(e.Id));
                        var applyDepartmentOuterCodes = applyDepartments.Select(x => x.OuterCode).ToList();
                        condition += $" and ApplyDepartmentCode in {parmSign}applyDepartmentOuterCodes ";
                        if (!userData.ContainsKey("applyDepartmentOuterCodes"))
                        {
                            parameters.Add("applyDepartmentOuterCodes", applyDepartmentOuterCodes);
                        }
                    }
                }

                // 医保卡号
                if (item.Key.Equals("medicalInsuranceNumber"))
                {
                    var value = item.Value as string;
                    if (!string.IsNullOrWhiteSpace(value))
                    {
                        parameters.Add("medicalInsuranceNumber", value);
                        condition += $" and MedicalInsuranceNumber={parmSign}{item.Key}";
                    }
                }
            }

            if (!string.IsNullOrEmpty(number))
            {
                parameters.Add("@number", number);
                if (funcSearchNumber != null) // number条件委托不为空
                {
                    condition += funcSearchNumber.Invoke();
                }
                else
                {
                    condition += @$" and 
                                    (   CONVERT(varchar(1000),PatientEMPI)={parmSign}number 
                                        or 
                                        IdCardNumber={parmSign}number 
                                        or 
                                        MedicalInsuranceNumber={parmSign}number 
                                        or 
                                        MedicalCardNumber={parmSign}number 
                                        or 
                                        PhoneNumber={parmSign}number 
                                        or 
                                        MedicalRecordNumber={parmSign}number 
                                        or 
                                        PhysicalExamNumber={parmSign}number 
                                        or 
                                        (CONVERT(varchar(1000),OutPatientNumber)={parmSign}number 
                                        or 
                                        (CONVERT(varchar(1000),InPatientNumber)={parmSign}number 
                                        or 
                                        CONVERT(varchar(1000),ApplyNumber)={parmSign}number 
                                        or
                                        Name={parmSign}number)";
                }
            }
            #endregion

            if (deviceTypeCodes!.Count > 0)
            {
                parameters.Add("deviceTypes", deviceTypeCodes);
                condition += $" and DeviceTypeCode in {parmSign}deviceTypes";
            }

            // 医疗机构代码
            var institutionCode = _configuration["InstitutionCode"];
            if (!string.IsNullOrWhiteSpace(institutionCode))
            {
                condition += $" and InstitutionCode = {institutionCode}";
            }

            if (actionAddConditions != null)
            {
                condition = actionAddConditions.Invoke(userData, condition);
            }
            
            string sql = $"select * from pacs_view_exam_apply_item " + condition;
            var res = (await conn.QueryAsync<HisExamApplyItemDto>(sql, parameters)).ToList();
            conn.Close();
            return res ;
        }

        /// <summary>
        /// 获取his申请单(可多个)下检查项目
        /// (用于自动预约接口)
        /// </summary>
        public async Task<List<HisExamApplyItemDto>> GetExamApplyItemsAsync(List<string> numbers)
        {
            var databaseType = _connectionProvider.GetDatabaseType();
            var connectionStr = _configuration["ConnectionStrings:HisDb"];
            if (string.IsNullOrEmpty(connectionStr))
            {
                throw new BusinessException(CustomErrorCodes.NoHisConnectionNotFund);
            }
            using var conn = _connectionProvider.GetDbConnection(connectionStr, databaseType);
            string parmSign = databaseType.GetParameterSign();
            conn.Open();

            string condition = $"where 1=1";
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            parameters!.Add("applyNumbers", numbers);
           
            condition += $" and CONVERT(varchar(1000),ApplyNumber) in {parmSign}applyNumbers";
            if (!string.IsNullOrEmpty(_configuration["InstitutionCode"]))
            {
                parameters!.Add("institutionCode", _configuration["InstitutionCode"]!);
                condition += $" and InstitutionCode = {parmSign}institutionCode";
            }
            string sql = $"select * from pacs_view_exam_apply_item " + condition;
            var res = (await conn.QueryAsync<HisExamApplyItemDto>(sql, parameters)).ToList();
            conn.Close();
            return res ;
        }
    }
}
